/*
 * Created on Sep 7, 2005
 *
 */
package org.mushroomdb.query.impl;

import java.util.HashMap;
import java.util.Map;

import org.mushroomdb.catalog.Column;
import org.mushroomdb.catalog.Register;
import org.mushroomdb.engine.EvaluationEngine;
import org.mushroomdb.engine.EvaluationEngineFactory;
import org.mushroomdb.engine.ResultSet;
import org.mushroomdb.exception.EvaluationEngineException;
import org.mushroomdb.exception.RDBMSRuntimeException;


/**
 * Helper for making common queries.
 * 
 * @author Matu
 *
 */
public class QueryHelper {
	private static QueryHelper instanceReference;
	private Map ids;
	
	/**
	 * Gets the QueryHelper instance.
	 * @return
	 */
	public static QueryHelper getInstance() {
		if (QueryHelper.instanceReference == null) {
			QueryHelper.instanceReference = new QueryHelper();
		}
		return QueryHelper.instanceReference;
	}
	
	/**
	 * Default private constructor.
	 */
	private QueryHelper() {
		this.ids = new HashMap();
	}
	
	/**
	 * Queries the desired column to obtain the next value that can be inserted.
	 * Column type must be BIGINT.
	 * 
	 * @param column the column for wich to find a new ID
	 * @return a long number for the next ID
	 */
	public synchronized long getNewId(Column column) {
		
		String key = column.getTable().getName() + '.' + column.getName();
		Long lastId = (Long) this.ids.get(key);
		if (lastId != null) {
			long newId = lastId.longValue() + 1;
			this.ids.put(key,new Long(newId));
			return newId;
		}
		
		SelectionQuery query = new SelectionQuery();
		query.addProjection(column);
		
		/** Retrieves IDs and searches for the biggest */
		long maxId = 0;
		EvaluationEngine evaluationEngine = EvaluationEngineFactory.getInstance();
		ResultSet resultSet = evaluationEngine.executeUnalterableQuery(query);
		try {
			
			/** ResultSet iteration */
			while (resultSet.hasNext()) {
				Register register = (Register) resultSet.next();
				long id = ((Long) register.getValue(1)).longValue();
				if (id > maxId) {
					maxId = id;
				}
			}
		} catch (EvaluationEngineException e) {
			throw new RDBMSRuntimeException(e);
		} finally {
			resultSet.close();
		}
		
		long newId = maxId + 1;
		this.ids.put(key,new Long(newId));
		return newId;
	}
}
